package com.neusoft.hifly.core.token;

import java.util.Date;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.neusoft.hifly.core.log.Log;
import com.neusoft.hifly.core.redis.RedisCache;
import com.neusoft.hifly.core.token.domain.TokenVO;
import com.neusoft.hifly.security.EncodeUtils;

/**
 * JWT组成 第一部分我们称它为头部（header),第二部分我们称其为载荷（payload)，第三部分是签证（signature)。
 */
public class JwtUtil {
	// header不能使用下划线。否则需要在Nginx中配置 underscores_in_headers on
	public static final String TOKEN_KEY = "token";

	public static final String USER_ID = "ID";
	public static final String LOGIN_NAME = "LN";
	public static final String USER_NAME = "UN";
	public static final String HOSPITALS = "HIDS";
	public static final String DEPARTMENTS = "DIDS";
	public static final String REGIONS = "RIDS";

	/**
	 * 加密Token
	 *
	 * @param secret
	 *            秘钥
	 * @param expire
	 *            过期时间（秒）
	 * @param vo
	 *            Token信息
	 * @param redisCache
	 *            缓存
	 * @return token
	 */
	public static String createPayLoad(final String secret, final long expire, final TokenVO vo,
			final RedisCache redisCache) {
		if (StringUtils.isEmpty(secret) || vo == null) {
			return null;
		}

		Algorithm algorithm = Algorithm.HMAC256(secret);
		String token = JWT.create()
				//设置过期时间为一个小时
				.withExpiresAt(new Date(System.currentTimeMillis() + expire * 1000))
				//设置负载
				.withClaim("ID", vo.getUserId()).withClaim("LN", vo.getLoginName()).withClaim("UN", vo.getUserName())
				.withClaim("HIDS", vo.getHospitals()).withClaim("DIDS", vo.getDepartments())
				.withClaim("RIDS", vo.getRegions()).sign(algorithm);

		if (redisCache != null) {
			redisCache.set(EncodeUtils.md5Encode(token), secret);
		}
		Log.debug("token = " + token);
		return token;
	}

	/**
	 * 解密Token中的数据
	 *
	 * @param secret
	 *            秘钥
	 * @param token
	 *            token
	 * @return 值
	 */
	public static Map<String, Claim> getByKey(final String secret, final String token) {
		if (StringUtils.isEmpty(secret) || StringUtils.isEmpty(token)) {
			return null;
		}
		Algorithm algorithm = Algorithm.HMAC256(secret);
		JWTVerifier jwtVerifier = JWT.require(algorithm).build();
		return jwtVerifier.verify(token).getClaims();
	}

}